/*  This program is free software; you can redistribute it and/or modify it
    under the terms of the GNU Lesser General Public License as published by
    the Free Software Foundation; either version 2.1 of the License, or (at
    your option) any later version.
    For more details, see the GNU Lesser General Public License (www.fsf.org
    or the COPYING file somewhere in the package)
 */

#ifndef OSGI_CONTEXT_HH
#define OSGI_CONTEXT_HH

#include "OSGi.hh"

/*! @file OSGi/Context.hh
    @brief Class OSGi::Context header.
    @author @ref Guillaume_Terrissol
    @date 12th December 2009 - 11th April 2014
    @note This file is distributed under the LGPL license.
    Refer to the file COPYING (or http://www.fsf.org) for more information.
 */

#include <memory>
#include <string>
#include <vector>

#include "BundleFactory.hh"
#include "Properties.hh"
#include "ServiceRegistry.hh"

namespace OSGi
{
//------------------------------------------------------------------------------
//                               Execution Context
//------------------------------------------------------------------------------

    /*! @brief Execution context.
        @version 0.7
     */
    class OSGI_EXPORT Context
    {
        OSGI_PRIVATE_CONSTRUCTOR()
    public:
        //! @name Friends
        //@{
        friend class BundleInstallerService;                                    //!< For access to registerInstalledBundle().
        friend class BundleMgr;                                                 //!< For access to registerResolvedBundle() and Context().
        //@}
        //! @name Types
        //@{
        using Ptr        = std::shared_ptr<Context>;                            //!< Pointer to context.
        using BundleList = std::vector<Bundle::Ptr>;                            //!< Pointer to bundle list.
        using Args       = std::vector<std::string>;                            //!< Argument list.
        //@}
        //! @name Constructor & destructor
        //@{
                                Context() = delete;                             //!< Disabled default constructor.
                                Context(const Args&        pArgs,
                                        BundleMgr*         pMgr,
                                        BundleFactory::Ptr pFactory,
                                        const Key&);                            //!< Constructor.
                                ~Context();                                     //!< Destructor.
        //! @anchor Context_Bundles @name Access to bundles
        //@{
        Bundle::Ptr             findBundle(const std::string& pName) const;     //!< Access by name.
        Bundle::Ptr             findBundle(int pId) const;                      //!< Access by id.
        BundleList              bundles() const;                                //!< Complete list.
        BundleList              resolvedBundles() const;                        //!< Working bundles.
        //@}
        //! @name Context elements
        //@{
        BundleMgr*              bundleMgr() const;                              //!< Bundle manager.
        BundleFactory::Ptr      bundleFactory() const;                          //!< Bundle factory.
        ServiceRegistry::Ptr    services() const;                               //!< Service list.
        Properties*             properties() const;                             //!< Global Properties.
        Properties*             properties(const std::string& pBundle) const;   //!< Arbitrary Bundle Properties.
        bool                    isVerbose() const;                              //!< Verbose mode status.
        //@}
        //! @anchor Context_Paths @name Paths
        //@{
        std::string             applicationPath() const;                        //!< Main path.
        std::string             cachePath() const;                              //!< Cache path.
        std::string             persistentPath() const;                         //!< Persistent data path.
        std::string             temporaryPath() const;                          //!< Temporary data path.
        //@}
        //! @name Logs
        //@{
        std::ostream&           out() const;                                    //!< Standard log.
        std::ostream&           err() const;                                    //!< Error log.
        //@}
        //! @anchor Context_Signals @name Signals
        //@{
        OSGI_DECL_SIGNAL(bundleInstalled,    Bundle::Ptr)                       //!< On Bundle installed.
        OSGI_DECL_SIGNAL(bundleResolving,    Bundle::Ptr)                       //!< On resolving Bundle.
        OSGI_DECL_SIGNAL(bundleResolved,     Bundle::Ptr)                       //!< On Bundle resolved.
        OSGI_DECL_SIGNAL(bundleStarting,     Bundle::Ptr)                       //!< On starting Bundle.
        OSGI_DECL_SIGNAL(bundleStarted,      Bundle::Ptr)                       //!< On Bundle started.
        OSGI_DECL_SIGNAL(bundleStopping,     Bundle::Ptr)                       //!< On stopping Bundle.
        OSGI_DECL_SIGNAL(bundleStopped,      Bundle::Ptr)                       //!< On Bundle stopped.
        OSGI_DECL_SIGNAL(bundleUninstalling, Bundle::Ptr)                       //!< On uninstalling Bundle.
        OSGI_DECL_SIGNAL(bundleUninstalled,  Bundle::Ptr)                       //!< On Bundle uninstalled.
        //@}

    private:
        //! @name Registering
        //@{
        void                    registerInstalledBundle(Bundle::Ptr pBundle);   //!< Registering of an installed bundle.
        void                    registerResolvedBundle(Bundle::Ptr pBundle);    //!< Registering of a resolved bundle.
        //@}
        OSGI_PIMPL()
    };
}

#endif  // OSGI_CONTEXT_HH
